package org.caenv.interpreter.util;

import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.caenv.interpreter.pojo.instructions.GoTo;
import org.caenv.interpreter.pojo.instructions.Instruction;
import org.caenv.interpreter.pojo.instructions.Scope;
import org.caenv.interpreter.pojo.instructions.comparator.EQ;
import org.caenv.interpreter.pojo.instructions.comparator.GE;
import org.caenv.interpreter.pojo.instructions.comparator.GT;
import org.caenv.interpreter.pojo.instructions.comparator.LE;
import org.caenv.interpreter.pojo.instructions.comparator.LT;
import org.caenv.interpreter.pojo.instructions.comparator.NEQ;
import org.caenv.interpreter.pojo.instructions.Interruption;
import org.caenv.interpreter.pojo.instructions.Mov;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;

public class SourceUtils {

    private final static Map<String, Class<? extends Instruction>> tagMap = new HashMap<String, Class<? extends Instruction>>();

    static {
        tagMap.put(Interruption.class.getSimpleName().toLowerCase(), Interruption.class);
        tagMap.put(GE.class.getSimpleName().toLowerCase(), GE.class);
        tagMap.put(GT.class.getSimpleName().toLowerCase(), GT.class);
        tagMap.put(LT.class.getSimpleName().toLowerCase(), LT.class);
        tagMap.put(LE.class.getSimpleName().toLowerCase(), LE.class);
        tagMap.put(EQ.class.getSimpleName().toLowerCase(), EQ.class);
        tagMap.put(NEQ.class.getSimpleName().toLowerCase(), NEQ.class);
        tagMap.put(GoTo.class.getSimpleName().toLowerCase(), GoTo.class);
        tagMap.put(Mov.class.getSimpleName().toLowerCase(), Mov.class);
    }

    public static Instruction getInstructionByName(String qName) {
        try {
            if(SourceUtils.tagMap.containsKey(qName)){
                return SourceUtils.tagMap.get(qName).newInstance();
            }else{
                System.err.print(qName + " nao foi encontrada!");
                return null;
            }
        } catch (InstantiationException ex) {
            return null;
        } catch (IllegalAccessException ex) {
            return null;
        }
    }

    public static Instruction buildInstruction(Instruction instruction, Attributes attributes) {

        Map<String, String> mapAttributes = new HashMap<String, String>();

        for (int i = 0; attributes != null && i < attributes.getLength(); i++) {

            String name = attributes.getQName(i).toLowerCase();
            String value = attributes.getValue(i);

            mapAttributes.put(name, value);

        }

        instruction.build(mapAttributes);

        return instruction;

    }

    public static Instruction buildInstruction(String qName, Attributes attributes) {
        return SourceUtils.buildInstruction(getInstructionByName(qName), attributes);
    }

    public static boolean isEscope(String qName) {
        Instruction instruction = SourceUtils.getInstructionByName(qName);

        if (instruction instanceof Scope) {
            return true;
        } else {
            return false;
        }
    }

    public static InputSource generateInputSourceByString(String code) {
        Reader reader = new StringReader(code);
        return new InputSource(reader);
    }

    public static InputSource[] generateInputSourceByString(String... codes) {
        List<InputSource> inputs = new ArrayList<InputSource>();

        for(String code : codes){
            inputs.add( SourceUtils.generateInputSourceByString(code) );
        }
        
        return inputs.toArray(new InputSource[inputs.size()]);
    }
}
